// 项目的根组件
// App -> index.js -> render -> public/index.html(root)
// 导入样式
// import './App.css'
//
// import {useRef, useState} from "react";

// const tabs = [
//     {
//         type: 'hot',
//         text: '最热'
//     },
//     {
//         type: 'time',
//         text: '最新'
//     }
// ]

// React中获取DOM
// 1. useRef生成ref对象，绑定到DOM标签
// 2. DOM可用的时候，ref.current获取DOM
// 渲染完毕之后DOM生成之后才可用
// function App() {
//     const inputRef = useRef(null)
//     const showDom = () => {
//         console.log('output-> inputRef.current::: ', inputRef.current)
//         console.dir(inputRef.current) // 展开显示
//     }
//     return (
//         <>
//             <input type='text' ref={inputRef}/>
//             <button onClick={showDom}>获取DOM</button>
//         </>
//     )
// }
//
// export default App;
// 父传子
// 1. 父组件传递数据 子组件标签身上绑定属性
// 2. 子组件接收数据 props的参数
// function Son({name}) {
//     return (<>
//         <h1>{name}</h1>
//         <div>This is Son Com</div>
//     </>)
// }
// function App() {
//     const name = 'This is app name'
//     return (<>
//         <Son name={name}/>
//     </>)
// }
//
// export default App;

//

// function Son({children}) {
//     return (<>
//         {children}
//     </>)
// }
// function App() {
//     return (<>
//         <Son>
//             Test-Data
//         </Son>
//     </>)
// }
//
// export default App;

// 受控表单
// function App() {
//     // 1. 声明一个react状态 - useState
//
//     // 2. 核心绑定流程
//     const [value, setValue] = useState('');
//
//     return (
//         <div className="App">
//             <input
//                 value={value}
//                 onChange={(e) => setValue(e.target.value)}
//                 type='text'/>
//         </div>
//     );
// }
//
// export default App;


// const list = [
//     {id: 1001, name: 'A'},
//     {id: 1002, name: 'B'},
//     {id: 1003, name: 'C'},
// ]
// const [isLoginV, setIsLoginV] = useState(false);
// const isLogin = true;
//
// const changeLogin = () => {
//     console.log('output-> isLoginV', isLoginV)
//     setIsLoginV(!isLoginV)
// }
// 调用useState实现一个计数器按钮
// const [form, setForm] = useState({name: 'wangzz'});
//
// const handleChangeForm = () => {
//     // right way
//     setForm({
//         name: 'change - wangzz'
//     })
// }
//
// const style = {
//     color: 'red', fontSize: '24px'
// }
// 评论列表
// const [comments, setComments] = useState([
//     {id: 1, desc: 'we are the world'},
//     {id: 2, desc: 'Testing - World'},
//     {id: 3, desc: 'biu!'},
// ]);
// return (
//     <div className="App">
//         <ul>
//             {
//                 comments.map(item => (
//                     <li key={item.id}>{item.desc}</li>
//                 ))
//             }
//         </ul>
//         {/*<button onClick={handleChangeForm}>change form</button>*/}
//         {/*React Basic*/}
//         {/*<h1>{form.name}</h1>*/}
//         {/*<hr/>*/}
//         {/*<span style={style}>this is span!</span>*/}
//         {/*<span className='titleBar'>this is span!</span>*/}
//         {/*/!*1. 使用引号传递变量*!/*/}
//         {/*{"We are the world!"}*/}
//         {/*/!*2. 使用JS变量*!/*/}
//         {/*{count}*/}
//         {/*/!*3. 函数调用和方法调用*!/*/}
//         {/*{handleDemo()}*/}
//         {/** ★ 列表渲染*/}
//         {/*JSX中使用原生JS的map方法遍历*/}
//         {/*key的作用：React框架内部使用，提升更新性能*/}
//         {/*<ul>*/}
//         {/*    {list.map(item => <li key={item.id}>{item.name}</li>)}*/}
//         {/*</ul>*/}
//         {/** ★ JSX中的条件渲染*/}
//         {/*React中可以使用逻辑与运算符&&、三元表达式（?:）实现基础的条件渲染*/}
//         {/*No.1: {flag && <span>this is span</span>}*/}
//         {/*No.2: {loading ? <span>loading ... </span> : <span>this is span</span>}*/}
//         {/*{isLogin && <span>Login User's name: Non-Name</span>} <br/>*/}
//         {/*{isLogin ? '已登录' : '未登录'}*/}
//         {/*<button onClick={changeLogin}>changeLogin</button>*/}
//         {/*/!*JSX中实现复杂条件渲染*!/*/}
//         {/*{getArticleTemplate()}*/}
//         {/*★ useState实现一个计数器按钮*/}
//     </div>
// );
// const [type, setType] = useState('hot');
// const handleTabChange = (type) => {
//     setType(type)
//     console.log('type::: ', type)
// }
import {createContext, useContext, useEffect, useState} from "react";
import axios from "axios";

{/*React Basic*/
}
{/*  /!*1. 使用引号传递变量*!/*/
}
{/*  {"We are the world!"}*/
}
{/*  /!*2. 使用JS变量*!/*/
}
{/*  {count}*/
}
{/*  /!*3. 函数调用和方法调用*!/*/
}
{/*  {handleDemo()}*/
}
{/*点击谁就把谁的type记录下来*/
}
{/*通过记录的type和每一项遍历的时候的type进行匹配，控制激活类的显示*/
}
{/*{*/
}
{/*    tabs.map(item =>*/
}
{/*        <span key={item.type}*/
}
{/*              onClick={() => handleTabChange(item.type)}*/
}
{/*              className={`nav-item ${type === item.type && 'active'}`}>{item.text}</span>)*/
}
{/*}*/
}


// const count = 999;
//
//
// function handleDemo() {
//     // setInterval(() => {
//     //     console.log('output-> new Date().getTime()::: ', new Date().getTime())
//     // }, 1000)
// }
//
// // 定义文章类型
// const articleType = 1; // 0 1 3
//
// // 核心函数（根据文章类型返回不同的JSX template)
// function getArticleTemplate() {
//     if(articleType === 0) {
//         return <div>无图文章</div>
//     }else if (articleType === 1) {
//         return <div>单图文章</div>
//     } else {
//         return <div>三图文章</div>
//     }
// }
// const count = 999;


// function handleDemo() {
//     setInterval(() => {
//         console.log('output-> new Date().getTime()::: ', new Date().getTime())
//     }, 1000)
// }

// React中的状态提升
// function A({ onGetAName }) {
//     const name = `> ${new Date().getTime()} <`;
//     return (
//         <div>
//             This is A component !
//             {/*箭头函数形式来调用事件函数*/}
//             <button onClick={() => onGetAName(name)}>sendAName</button>
//         </div>
//     )
// }
//
// function B({name}) {
//     return (
//         <>
//             Transfer Data from A: {name}
//             This is B component !
//         </>
//     )
// }
//
//
// // 1. 通过子传父 A -> App
// // 2. 通过父传子 App -> B
//
// function App() {
//     const [name, setName] = useState('');
//     const getAName = (name) => {
//         console.log('【print】name: ', name)
//         setName(name)
//     }
//
//     return (<>
//         This is App
//         <A onGetAName = {getAName}/>
//         <B name={name}/>
//     </>)
// }
//
// export default App;

// 使用context机制跨层级组件通信

// 1. 使用createContext方法创建一个上下文对象
// 2. 在顶层组件 通过Provider组件提供数据 <Ctx.Provider value={}></Ctx.Provider>
// 3. 在底层组件 通过useContext钩子函数使用数据


// useEffect的使用
// function A() {
//     return (<>
//         This is A component
//     </>)
// }
//
// function B() {
//
//     return (<>
//         This is B component::::
//     </>)
// }
//
// const URL = 'http://geek.itheima.net/v1_0/channels'


// function App() {
//     const [channels, setChannels] = useState([])
//     useEffect(() => {
//         console.log('没有依赖项的情况下在初始渲染和每次组件更新时触发', )
//     })
//
//     useEffect(() => {
//       console.log('空数组的时候是在初始渲染的时候触发', )
//     }, [])
//
//     useEffect(() => {
//         console.log('存在依赖项的情况下是在初始渲染以及依赖项更新的时候触发')
//     }, channels)
//     useEffect(() => {
//         loadChannels().then(r => console.log('error: ', r));
//     }, []); // 空数组 - 页面渲染完毕之后只会执行一次
//     const loadChannels = async () => {
//         // 额外的操作 - 获取频道列表
//         let response = await fetch(URL);
//         let res = await response.json();
//         console.log('data::: ', res.data.channels);
//         setChannels(res.data.channels);
//     }
//
//     return (<>
//         <hr/>
//         <ul>
//             {channels.map(item => (<li key={item.id}> {item.name}</li>))}
//         </ul>
//         <hr/>
//         this is App
//         <A/>
//         <B/>
//     </>)
// }
//
//
// export default App;

// 1. 没有依赖项 - 初始渲染 + 组件更新
// 2. 空数组 - 初始渲染
// 3. 依赖项 - 初始渲染 + 依赖项更新

// function App() {
//     // 1. 没有依赖项 - 每次都会更新
//     useEffect(() => {
//         console.log('每次更新都会触发！', )
//     })
//
//     let [count, setCount] = useState(0);
//
//     const changeCount = () => {
//         setCount(++count);
//     }
//
//     useEffect(() => {
//         console.log('空数组的时候只会在初始渲染的时候触发', )
//     }, [])
//
//     useEffect(() => {
//         return () => {
//             console.log('初始渲染以及count发生变化的时候触发', )
//         };
//     }, [count]);
//
//     return (<>
//         <button onClick={changeCount}>change count</button>
//     </>)
// }
// // 每次更新都会触发！
// // 空数组的时候只会在初始渲染的时候触发
// // 初始渲染以及count发生变化的时候触发
// // 每次更新都会触发！
// // 初始渲染以及count发生变化的时候触发
// // 每次更新都会触发！
//
// export default App;

// 问题：布尔切换的逻辑 和 当前组件耦合在一起 无法进行复用

// 解决思路： 自定义Hook
// 1. 声明一个以use大头的函数
// 2. 在函数体内封装可复用的逻辑（只要是可复用的逻辑）
// 3. 把组件中用到的状态或回调 return出去(以对象或者数组
// 4. 在哪个组件中要使用到这个逻辑，就执行这个函数，解构出来状态和回调进行使用

// 优化需求 - 自定义Hook函数封装数据请求
// 封装请求数据的Hook

// 抽象原则： App作为“智能组件” 负责数据的获取，Item作为“UI组件”负责数据的渲染

// function useGetList() {
//     // 获取接口数据
//     const [commentList, setCommentList] = useState([]);
//
//     useEffect(() => {
//         // 请求接口数据
//         async function getList() {
//             const res = await axios.get('http://localhost:3004/list')
//             setCommentList(res.data);
//         }
//         getList()
//     }, [])
//
//     return {
//         commentList,
//         setCommentList,
//     }
// }
//
// function Items({item}) {
//     return (
//         <>
//
//         </>
//     )
// }
// function App() {
//     const {commentList, setCommentList } = useGetList();
//     console.log('commentList::: ', commentList)
//     return (<>
//         <div>
//             Test
//             <ul>
//                 {
//                     commentList.map(item => {
//                         <li>{item}</li>
//                     })
//                 }
//             </ul>
//         </div>
//     </>)
// }
//
//
// export default App;
// Redux - 集中状态管理工具

function App() {
    return (<>

    </>)
}


export default App;














